package com.lang;

import org.junit.Test;

import java.lang.reflect.Field;

public class IntegerDemo {



    /**
     * 负数的话转化为unsign有问题。因为unsign未无符号数。会进行  ((long) x) & 0xffffffffL;运算
     */
    @Test
    public void toUnsignedString(){
        Integer a = -100;
        String sa = Integer.toUnsignedString(a);
        System.out.println(sa);

        Integer b = 100;
        String sb = Integer.toUnsignedString(b);
        System.out.println(sb);
    }

    /**
     * 判断是整数负数和0
     */
    @Test
    public void signum(){
        System.out.println(Integer.signum(100));
        System.out.println(Integer.signum(0));
        System.out.println(Integer.signum(-999));
    }

    /**
     * 转化为无符号位的16进制，负数不适用，所有的快捷的转化为特定进制的方法都是针对于无符号位的
     */
    @Test
    public void toHexString(){
        Integer t = -154;
        System.out.println("转化为16进制"+Integer.toString(t,16));
        System.out.println("先变为无符号位，然后再进行转换" +Integer.toHexString(-154));
        System.out.println(Integer.toHexString(154));
    }

    /**
     * 将指定进制的字符串转化为十进制数字,只能匹配有符号位的数字
     * 等价于 valueOf ，只是返回值不同。
     */
    @Test
    public void parseInt(){
        int t = Integer.parseInt("f9a", 16);
        Integer t1 = Integer.valueOf("f9a", 16);
        System.out.println(t);
        String s = Integer.toHexString(-154);
        //报错 因为  ffffff66 超过 integer所能表示的最大值 0x7fffffff
        Integer.parseInt(s, 16);
    }



    /**
     * 将无符号数字进行转化
     */
    @Test
    public void parseUnsignedInt(){
//        这里其实是序列化和反序列化问题，第一步转化其实已经是错误的数据了，然后反序列化回来又正常了。
        String s = Integer.toHexString(-154);//1
        System.out.println(s);
        int t = Integer.parseUnsignedInt(s, 16);
        System.out.println(t);
    }


    /**
     * 使用查过有符号位的数据会转变为负数
     */
    @Test
    public void integerConstruct(){
        Integer integer = new Integer(0x7fffffff+1);
        System.out.println(integer);
        integer.toString();
    }

    /**
     * 从环境变量中取值
     */
    @Test
    public void getInteger(){
        //当环境变量中有 jdk.internal.FileHandlerLogging.maxLocks 则使用该key的值
        Integer integer = Integer.getInteger(
                "jdk.internal.FileHandlerLogging.maxLocks",
                10);
        System.out.println(integer);
    }

    /**
     * 自动匹配指定数据类型
     */
    @Test
    public void decode(){
        //16进制
        String str = "0x9f";
        Integer integer = Integer.decode(str);
        System.out.println(integer);

        str = "+123";
        integer = Integer.decode(str);
        System.out.println(integer);

        //16进制
        str = "#f";
        integer = Integer.decode(str);
        System.out.println(integer);

        //8进制
        str = "010";
        integer = Integer.decode(str);
        System.out.println(integer);
    }


    //除法
    @Test
    public void divide(){
        //除数
        int i = Integer.divideUnsigned(10, 3);
        System.out.println(i);
        //余数
        int i1 = Integer.remainderUnsigned(10, 3);
        System.out.println(i1);
    }

    /**
     * 找到该数字的最高位，二进制下的首位非0 位，负数就是最高位
     */
    @Test
    public void highestOneBit(){
        Integer i = 900;
        System.out.println(Integer.toBinaryString(i));
        int i1 = Integer.highestOneBit(i);
//        System.out.println(i1);
        System.out.println(Integer.toBinaryString(i1));
    }

    /**
     * 找到该数字的非0最低位
     */
    @Test
    public void lowestOneBit(){
//        Integer i = 990;
//        System.out.println(Integer.toString(i, 2));
//        int i1 = Integer.lowestOneBit(i);
////        System.out.println(i1);
//        System.out.println(Integer.toString(i1, 2));
//
//        System.out.println(Integer.toString(-10, 2));

        //正数与负数的与运算 为 该数二进制最低非0位的值
        int s = 10;
        System.out.println(Integer.toBinaryString(-s));
        System.out.println(Integer.toBinaryString(s));
        System.out.println(Integer.toBinaryString(s&-s));

    }

    @Test
    public void numberOfLeadingZeros(){
        Integer i = 900;
        System.out.println(Integer.toBinaryString(i));
        int i1 = Integer.highestOneBit(i);
//        System.out.println(i1);
        System.out.println(Integer.toBinaryString(i1));
    }


    //int 和 Integer 可以进行重载，两个是不同类型
    public void ff(int p){
        return ;
    }
    public void ff(Integer p){
        return ;
    }




    /**
     * 判断Integer是值传递还是引用传递？->引用传递，因为  java.lang.Integer#value 使用final修饰无法改变。
     * 在field+=1后field是一个新的对象了
     */
    @Test
    public void test01() {
        Integer field = 0;
        f(field);
        System.out.println(field);
    }

    private void f(Integer field) {
        System.out.println(field);//1
        field += 1;
        System.out.println(field);//2
    }

    /**
     * 空指针异常，当Integer对象为null时，==操作不会抛异常
     */
    @Test
    public  void test02(){
        Integer i  = null;
        if(null == i){
            System.out.println(" i is null ");
        }
        //空的话可以使用== 但是大于小于这些会报错
        if(i>0){
            System.out.println("aaaaa");
        }
        Integer b = 3;
        b.compareTo(i);//抛异常

        if(i<0){
            System.out.println("大于或者小于会抛异常");
        }

        String s = Integer.toString(i);//在执行这句话就报错了，估计是编译优化导致的
        System.out.println(s);
    }



    @Test
    public void test04(){
        int a = 1000;
        int b = 1000;
        System.out.println(a==b);//true
        Integer c= 1000;
        Integer d = 1000;
        System.out.println(c==d);//false
        System.out.println(c==a);//true
    }


    /**
     * 输出2+2 = 5
     * Integer中cache缓存了部分数据，下面第五步将 缓存的数据4变成了5，导致2+2变成了5
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    @Test
    public  void test05() throws NoSuchFieldException, IllegalAccessException {

        Class cache = Integer.class.getDeclaredClasses()[0]; //1
        Field myCache = cache.getDeclaredField("cache"); //2
        myCache.setAccessible(true);//3

        Integer[] newCache = (Integer[]) myCache.get(cache); //4
        newCache[132] = newCache[133]; //5

        int a = 2;
        int b = a + a;
        System.out.printf("%d + %d = %d", a, a, b); //
    }


    public static void main(String[] args) {

    }

}
